﻿Imports System.ComponentModel
Imports System.Windows.Forms
Public Class FileSystem

#Region "Variables"
    Private filters As List(Of Filter)
    Private saveFilters As List(Of Filter)
    Private _work As Dictionary(Of Integer, Row)
    Private _valid As List(Of KeyValuePair(Of Integer, Row))

    Private _worked As Integer = 0

    Private _isLoad As Boolean = False
    Private _isEdit As Boolean = False
    Private _isSave As Boolean = False

    Private _openFilterIndex As Integer = -1
    Private _saveFilterIndex As Integer = -1
    Private _importFilterIndex As Integer = -1

    Private _openDialog As OpenFileDialog
    Private _saveDialog As SaveFileDialog
    Private _importDialog As OpenFileDialog

    Private _openFile As New File
    Private _saveFile As New File
    Private _importFile As New File
    Private _draftFile As New File

    Public Shadows Event OpenFileOk As EventHandler(Of DialogEventArgs)
    Public Shadows Event SaveFileOk As EventHandler(Of DialogEventArgs)
    Public Shadows Event ImportFileOk(sender As Object, e As DialogEventArgs)
    Public Shadows Event ReadCompleted As EventHandler(Of CompleteEventArgs)
    Public Shadows Event SaveCompleted As EventHandler(Of CompleteEventArgs)
    Public Shadows Event ImportCompleted As EventHandler(Of CompleteEventArgs)
    Public Shadows Event FilterIndexChanged As EventHandler(Of FilterEventArgs)
#End Region

    Public Sub New(filters() As Filter)
        'Set data list
        _work = New Dictionary(Of Integer, Row)
        _valid = New List(Of KeyValuePair(Of Integer, Row))

        _isLoad = False
        _isEdit = False
        _isSave = False

        'Set filter file info
        Me.filters = filters.ToList

        'Set open file dialog info
        Me.OpenDialog = New OpenFileDialog()
        With Me.OpenDialog
            .AddExtension = True
            .AutoUpgradeEnabled = True
            .CheckFileExists = True
            .CheckPathExists = True
            .Filter = Me.ReadFilter
            .FilterIndex = 0 'filters.Count
            .Multiselect = False
            .RestoreDirectory = False
            .ShowHelp = False
            .SupportMultiDottedExtensions = True
            .ValidateNames = True
            '.Title = "Select the translate file:"

            AddHandler .FileOk, AddressOf OpenDialog_FileOk
        End With

        'Set import file dialog info
        Me.ImportDialog = New OpenFileDialog()
        With Me.ImportDialog
            .AddExtension = True
            .AutoUpgradeEnabled = True
            .CheckFileExists = True
            .CheckPathExists = True
            .Filter = Me.ReadFilter
            .FilterIndex = 0 'filters.Count
            .Multiselect = False
            .RestoreDirectory = False
            .ShowHelp = False
            .SupportMultiDottedExtensions = True
            .ValidateNames = True
            '.Title = "Select the translate file:"

            AddHandler .FileOk, AddressOf ImportDialog_FileOk
        End With

        'Set save file dialog info
        Me.SaveDialog = New SaveFileDialog()
        With Me.SaveDialog
            .AddExtension = True
            .AutoUpgradeEnabled = True
            .CheckFileExists = False
            .CheckPathExists = True
            .InitialDirectory = GetFileDirectoryName(Me.OpenDialog.FileName)
            .OverwritePrompt = True
            .RestoreDirectory = False
            .ShowHelp = False
            .SupportMultiDottedExtensions = True
            .ValidateNames = True
            '.Title = "Select the path for save:"

            AddHandler .FileOk, AddressOf SaveDialog_FileOk
        End With

        Me.CurrentIndex = -1
    End Sub

    Public Sub Open(fileName As String)
        OpenDialog.FileName = fileName
        OpenDialog_FileOk(OpenDialog, New CancelEventArgs(Me.OpenFile.Path = fileName))
    End Sub
    Public Function Read(Optional onReadCompleted As EventHandler(Of CompleteEventArgs) = Nothing) As Dictionary(Of Integer, Row)
        Dim state As Boolean = True
        Dim ex As New Exception("")
        Try

            Select Case Me.OpenFile.Extension.ToLower
                Case ".lng"
                    _work = Readlng(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".ini"
                    _work = ReadIni(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".ini1"
                    _work = ReadIni1(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".srt"
                    _work = ReadSrt(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".ass"
                    _work = ReadAss(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".xtf"
                    _work = ReadXtf(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".xls"
                    _work = ReadXls(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".xlsx"
                    _work = ReadXlsx(Me.OpenFile.Path)
                    Me.CurrentIndex = -1
                Case ".udraft"
                    Dim index As Integer = -1
                    _work = ReadDraft(Me.OpenFile.Path, _draftFile, index)
                    Call setSaveFilter(Me.DraftFile.Extension)
                    Me.CurrentIndex = index
            End Select
            _isLoad = True
            _isEdit = False
            _isSave = False

        Catch ex : state = False
        Finally
            Me.Worked = 0
            _valid = Me.Work.Where(Function(match) match.Value.Show).ToList()
            If Me.OpenFile.Extension.ToLower = ".udraft" Then Call CalcState()
            If onReadCompleted IsNot Nothing Then AddHandler Me.ReadCompleted, onReadCompleted
            RaiseEvent ReadCompleted(Me, New CompleteEventArgs(state, ex.Message))
            If onReadCompleted IsNot Nothing Then RemoveHandler Me.ReadCompleted, onReadCompleted
        End Try
        Return Me.Work
    End Function
    Public Sub Import(fileName As String)
        ImportDialog.FileName = fileName
        ImportDialog_FileOk(ImportDialog, New CancelEventArgs(Me.ImportFile.Path = fileName))
    End Sub
    Public Function Import(Optional onImportCompleted As EventHandler(Of CompleteEventArgs) = Nothing) As Dictionary(Of Integer, Row)
        Dim state As Boolean = True
        Dim ex As New Exception("")
        Try
            Dim work As New Dictionary(Of Integer, Row)
            Select Case Me.ImportFile.Extension.ToLower
                Case ".lng" : work = Readlng(Me.ImportFile.Path)
                Case ".ini" : work = ReadIni(Me.ImportFile.Path)
                Case ".ini1" : work = ReadIni1(Me.ImportFile.Path)
                Case ".srt" : work = ReadSrt(Me.ImportFile.Path)
                Case ".ass" : work = ReadAss(Me.ImportFile.Path)
                Case ".xtf" : work = ReadXtf(Me.ImportFile.Path)
                Case ".xls" : work = ReadXls(Me.ImportFile.Path)
                Case ".xlsx" : work = ReadXlsx(Me.ImportFile.Path)
            End Select

            Me.Worked = 0
            For Each row In Me.GetValid
                Dim query = work.Where(Function(match) match.Value.Key = row.Value.Key AndAlso match.Value.Root = row.Value.Root)
                With Me.Work(row.Key)
                    If query IsNot Nothing AndAlso query.Count() > 0 Then .Target = query(0).Value.Source
                    If .Source <> .Target AndAlso .Target <> "" Then Me.Worked += 1 : _isEdit = True
                End With
            Next
        Catch ex : state = False
        Finally
            If onImportCompleted IsNot Nothing Then AddHandler Me.ImportCompleted, onImportCompleted
            RaiseEvent ImportCompleted(Me, New CompleteEventArgs(state, ex.Message))
            If onImportCompleted IsNot Nothing Then RemoveHandler Me.ImportCompleted, onImportCompleted
        End Try

        Return Me.Work
    End Function
    Public Sub Save(Optional onSaveCompleted As EventHandler(Of CompleteEventArgs) = Nothing)
        Me.SaveAs(Me.OpenFile.Path, onSaveCompleted)
    End Sub
    Public Sub SaveAs(Optional onSaveCompleted As EventHandler(Of CompleteEventArgs) = Nothing)
        Me.SaveAs(Me.SaveFile.Path, onSaveCompleted)
    End Sub
    Public Sub SaveAs(filename As String, Optional onSaveCompleted As EventHandler(Of CompleteEventArgs) = Nothing)
        Dim state As Boolean = True
        Dim ex As New Exception("")
        Try
            Select Case GetFileExtension(filename).ToLower
                Case ".lng" : Savelng(filename, Me.Work)
                Case ".ini" : SaveIni(filename, Me.Work)
                Case ".ini1" : SaveIni1(filename, Me.Work)
                Case ".srt" : SaveSrt(filename, Me.Work)
                Case ".ass" : SaveAss(filename, Me.Work)
                Case ".xtf" : SaveXtf(filename, Me.Work)
                Case ".xls" : SaveXls(filename, Me.Work)
                Case ".xlsx" : SaveXlsx(filename, Me.Work)
                Case ".udraft" : SaveDraft(filename, If(Me.OpenFile.Extension.ToLower() = ".udraft", Me.DraftFile, Me.OpenFile), Me.Work, Me.CurrentIndex)
            End Select
            _isEdit = False
            _isSave = True
        Catch ex : state = False
        Finally
            If onSaveCompleted IsNot Nothing Then AddHandler Me.SaveCompleted, onSaveCompleted
            RaiseEvent SaveCompleted(Me, New CompleteEventArgs(state, ex.Message))
            If onSaveCompleted IsNot Nothing Then RemoveHandler Me.SaveCompleted, onSaveCompleted
        End Try
    End Sub

    Public Function GetSimilarityList(key As String, Optional minSimilarityLong As Double = 85, Optional minSimilarityShort As Double = 70, Optional maxToleranceLong As Double = 20, Optional maxToleranceShort As Double = 10) As List(Of CompareResult)
        Return Module1.GetSimilarityList(key, Me.Work, minSimilarityLong, minSimilarityShort, maxToleranceLong, maxToleranceShort)
    End Function
    Public Function GetContainsList(key As String) As List(Of KeyValuePair(Of Integer, Row))
        Return Me.Work.Where(Function(match) match.Value.Show AndAlso match.Value.Target <> "" AndAlso match.Value.Target.ToLower <> match.Value.Source.ToLower AndAlso (match.Value.Source.ToLower.Contains(key.ToLower) OrElse match.Value.Target.ToLower.Contains(key.ToLower))).ToList()
    End Function

    Private Sub CalcState()
        Me.Worked = Me.GetValid.LongCount(Function(match) match.Value.Source <> match.Value.Target AndAlso match.Value.Target <> "")
    End Sub
    Private Sub setSaveFilter(extension As String)
        saveFilters = New List(Of Filter)
        Dim filterIndex As Integer = filters.FindIndex(Function(filter) filter.Contains(extension))
        If filterIndex > -1 Then
            For Each ext In filters(filterIndex).Output
                Dim filter = filters.Find(Function(item) item.IsIndex AndAlso item.Input.Contains(ext))
                If filter Is Nothing Then Continue For
                saveFilters.Add(New Filter(filter.Name, ext))
            Next
        End If

        SaveDialog.Filter = Me.SaveFilter
    End Sub

    Private Sub OpenDialog_FileOk(sender As Object, e As CancelEventArgs)
        If e.Cancel Then Return

        _openFile = New File(OpenDialog.FileName)
        Dim oldFilterIndex As Integer = Me.OpenFilterIndex
        _openFilterIndex = filters.FindIndex(Function(filter) filter.Contains(Me.OpenFile.Extension))
        Call setSaveFilter(Me.OpenFile.Extension)
        RaiseEvent FilterIndexChanged(Me, New FilterEventArgs(Me.OpenFilterIndex, oldFilterIndex <> Me.OpenFilterIndex))
        RaiseEvent OpenFileOk(sender, New DialogEventArgs(Me.OpenFilterIndex, Me.OpenFile))
    End Sub
    Private Sub SaveDialog_FileOk(sender As Object, e As CancelEventArgs)
        If e.Cancel Then Return

        _saveFile = New File(SaveDialog.FileName)
        _saveFilterIndex = saveFilters.FindIndex(Function(filter) filter.Contains(Me.SaveFile.Extension))
        RaiseEvent SaveFileOk(sender, New DialogEventArgs(Me.SaveFilterIndex, Me.SaveFile))
    End Sub
    Private Sub ImportDialog_FileOk(sender As Object, e As CancelEventArgs)
        If e.Cancel Then Return

        _importFile = New File(ImportDialog.FileName)
        _importFilterIndex = filters.FindIndex(Function(filter) filter.Contains(Me.ImportFile.Extension))
        RaiseEvent ImportFileOk(sender, New DialogEventArgs(Me.ImportFilterIndex, Me.ImportFile))
    End Sub

    Public ReadOnly Property IsLoad() As Boolean
        Get
            Return _isLoad
        End Get
    End Property
    Public Property IsEdit() As Boolean
        Get
            Return _isEdit
        End Get
        Set(value As Boolean)
            _isEdit = value
        End Set
    End Property
    Public ReadOnly Property IsSave() As Boolean
        Get
            Return _isSave
        End Get
    End Property

    Public ReadOnly Property ReadFilter As String
        Get
            Dim list As New List(Of String)
            For Each filter In filters
                If filter.IsHide Then Continue For
                list.Add(filter.InputString)
            Next
            Return Join(list.ToArray, "|")
        End Get
    End Property
    Public ReadOnly Property SaveFilter As String
        Get
            Dim list As New List(Of String)
            For Each filter In saveFilters
                If filter.IsHide Then Continue For
                list.Add(filter.InputString)
            Next
            Return Join(list.ToArray, "|")
        End Get
    End Property

    Public ReadOnly Property OpenFilterIndex As Integer
        Get
            Return _openFilterIndex
        End Get
    End Property
    Public ReadOnly Property SaveFilterIndex As Integer
        Get
            Return _saveFilterIndex
        End Get
    End Property
    Public ReadOnly Property ImportFilterIndex As Integer
        Get
            Return _importFilterIndex
        End Get
    End Property

    Public ReadOnly Property OpenFile As File
        Get
            Return _openFile
        End Get
    End Property
    Public ReadOnly Property ImportFile As File
        Get
            Return _importFile
        End Get
    End Property
    Public ReadOnly Property SaveFile As File
        Get
            Return _saveFile
        End Get
    End Property
    Public ReadOnly Property DraftFile As File
        Get
            Return _draftFile
        End Get
    End Property
    Public ReadOnly Property ValidFile As File
        Get
            Return If(Me.OpenFile.Extension.Equals(".UDraft"), Me.DraftFile, Me.OpenFile)
        End Get
    End Property

    Public Property Work As Dictionary(Of Integer, Row)
        Get
            Return _work
        End Get
        Set(value As Dictionary(Of Integer, Row))
            _work = value
        End Set
    End Property
    Public ReadOnly Property ToDataTable As DataTable
        Get
            Dim Dt As New DataTable
            Dt.Columns.Add("Index")
            Dt.Columns.Add("No")
            Dt.Columns.Add("Key")
            Dt.Columns.Add("Source")
            Dt.Columns.Add("Target")

            For Each row In Me.GetValid
                With Me.Work(row.Key)
                    Dt.Rows.Add({ .Index, .Number, .Key, .Source, ""})
                End With
            Next

            Return Dt
        End Get
    End Property
    Public ReadOnly Property GetValid As List(Of KeyValuePair(Of Integer, Row))
        Get
            Return _valid
        End Get
    End Property
    Public ReadOnly Property Count As Integer
        Get
            Return Me.GetValid.Count
        End Get
    End Property
    Public Property Worked As Integer
        Get
            Return _worked
        End Get
        Set(value As Integer)
            _worked = value
        End Set
    End Property
    Public ReadOnly Property GetState As State
        Get
            Return New State(Me.Count, Me.Worked)
        End Get
    End Property

    Public Property OpenDialog As OpenFileDialog
        Get
            Return _openDialog
        End Get
        Set(value As OpenFileDialog)
            _openDialog = value
        End Set
    End Property
    Public Property SaveDialog As SaveFileDialog
        Get
            Return _saveDialog
        End Get
        Set(value As SaveFileDialog)
            _saveDialog = value
        End Set
    End Property
    Public Property ImportDialog As OpenFileDialog
        Get
            Return _importDialog
        End Get
        Set(value As OpenFileDialog)
            _importDialog = value
        End Set
    End Property

    Public Property CurrentIndex As Integer
End Class